﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace Team6_Algorithms.Filters
{
    /// <summary>
    /// Made by Dylan Snel
    /// </summary>
    public class Masking
    {
        public static int RedMean;
        public static int GreenMean;
        public static int BlueMean;

        /// <summary>
        /// Applies the masking filter
        /// </summary>
        public static bool applyFilter(Bitmap B, Mask MASK)
        {



            Bitmap bSrc = (Bitmap)B.Clone();

            BitmapData BmData = B.LockBits(new Rectangle(0, 0, B.Width, B.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData BmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = BmData.Stride;

            System.IntPtr Scan0 = BmData.Scan0;
            System.IntPtr SrcScan0 = BmSrc.Scan0;

            unsafe
            {
                byte* p = (byte*)(void*)Scan0;
                byte* pSrc = (byte*)(void*)SrcScan0;

                p += ((MASK.Size - 1) / 2) * stride;
                p += ((MASK.Size - 1) / 2) * 3;
                pSrc += ((MASK.Size - 1) / 2) * stride;
                pSrc += ((MASK.Size - 1) / 2) * 3;

                int nOffset = B.Width % 4;
                int nWidth = B.Width - MASK.Size + 1;
                int nHeight = B.Height - MASK.Size + 1;

                for (int y = 0; y < nHeight; ++y)
                {
                    for (int x = 0; x < nWidth; ++x)
                    {
                        calculateMeans(pSrc, MASK, stride);
                        p[0] = (byte)BlueMean;
                        p[1] = (byte)GreenMean;
                        p[2] = (byte)RedMean;
                        p += 3;
                        // add 3 pixels to the address? possibly
                        // at least, this is moving through the pic
                        // or maybe 3 bytes
                        pSrc += 3;
                    }
                    // but then here we add the padding... at the end of every row
                    pSrc += -3 + ((MASK.Size - 1) / 2) * 3;
                    p += -3 + ((MASK.Size - 1) / 2) * 3;
                    p += nOffset;
                    pSrc += nOffset;
                }
            }

            B.UnlockBits(BmData);
            bSrc.UnlockBits(BmSrc);

            return true;
        }

        /// <summary>
        /// Calculate the mean value
        /// </summary>
        private static unsafe void calculateMeans(byte* P, Mask MASK, int STRIDE)
        {
            RedMean = 0;
            GreenMean = 0;
            BlueMean = 0;
            int yCounter = 0;
            int xCounter = 0;
            byte* CalcPointer = P;
            int Boundary = (MASK.Size - 1) / 2;
            for (int y = -Boundary; y <= Boundary; ++y)
            {

                for (int x = -Boundary; x <= Boundary; ++x)
                {
                    RedMean += CalcPointer[2 + (x * 3) + (y * STRIDE)] * MASK.MaskValues[xCounter][yCounter];
                    GreenMean += CalcPointer[1 + (x * 3) + (y * STRIDE)] * MASK.MaskValues[xCounter][yCounter];
                    BlueMean += CalcPointer[0 + (x * 3) + (y * STRIDE)] * MASK.MaskValues[xCounter][yCounter];

                    xCounter++;

                }
                xCounter = 0;
                yCounter++;
            }
            RedMean /= MASK.Total;
            GreenMean /= MASK.Total;
            BlueMean /= MASK.Total;

            RedMean += MASK.OffSet;
            GreenMean += MASK.OffSet;
            BlueMean += MASK.OffSet;
            if (RedMean > 255)
            {
                RedMean = 255;
            }
            if (GreenMean > 255)
            {
                GreenMean = 255;
            }
            if (BlueMean > 255)
            {
                BlueMean = 255;
            }
            if (RedMean < 0)
            {
                RedMean = 0;
            }
            if (GreenMean < 0)
            {
                GreenMean = 0;
            }
            if (BlueMean < 0)
            {
                BlueMean = 0;
            }



        }
    }
}
